package com.ihg.hiex.admin.web.controller.session;

import java.util.List;
import java.util.Map;

import org.apache.commons.io.FilenameUtils;
import org.apache.commons.lang3.time.DateUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.servlet.ModelAndView;

import com.demo2do.core.entity.result.HttpResult;
import com.ihg.hiex.admin.entity.upload.OnlineAccount;
import com.ihg.hiex.admin.entity.upload.OnlineReport;
import com.ihg.hiex.admin.entity.upload.OnlineReportUpload;
import com.ihg.hiex.admin.entity.upload.ReportType;
import com.ihg.hiex.admin.handler.FileHandler;
import com.ihg.hiex.admin.handler.OnlineAccountUploadHandler;
import com.ihg.hiex.admin.handler.support.FileStorage;
import com.ihg.hiex.admin.service.account.DelegateService;
import com.ihg.hiex.admin.service.session.SessionReportService;
import com.ihg.hiex.admin.service.session.SessionService;
import com.ihg.hiex.admin.service.session.SessionTaskService;
import com.ihg.hiex.admin.web.resolver.Secure;
import com.ihg.hiex.admin.web.view.ExcelTemplateView;
import com.ihg.hiex.entity.session.Session;
import com.ihg.hiex.entity.session.SessionAttribute;
import com.ihg.hiex.entity.session.after.SessionReport;
import com.ihg.hiex.entity.session.participator.Type;
import com.ihg.hiex.entity.session.task.SessionTask;
import com.ihg.hiex.entity.user.Delegate;

/**
 * 
 * @author dan
 *
 */
@Controller
@RequestMapping("")
public class SupervisorSessionController {
    
    @Autowired
    private SessionService sessionService;
    
    @Autowired
    private SessionReportService sessionReportService;
    
    @Autowired
    private DelegateService delegateService;
    
    @Autowired
    private SessionTaskService sessionTaskService;
    
    @Autowired
    private OnlineAccountUploadHandler onlineAccountUploadHandler;
    
    @Autowired
    private FileHandler fileHandler;
    
    private static final Logger logger = LoggerFactory.getLogger(SupervisorSessionController.class);
    
    /**
     * 
     * @param sessionId
     * @return
     */
    @RequestMapping(value = "/active-sessions/{sessionId}", method = RequestMethod.GET)
    public ModelAndView activeSessionView(@PathVariable("sessionId") Long sessionId) {
        
        ModelAndView modelAndView = new ModelAndView("session/supervisor/active-session-view");
        
        Session session = sessionService.load(sessionId);
        modelAndView.addObject("session", session);
        
        // list session data report
        Map<String, SessionAttribute> sessionAttributes = sessionService.listSessionAttribute(session, new String[]{"wave-data", "swift-data"});
        modelAndView.addObject("sessionAttributes", sessionAttributes);
        
        // get session start event
        modelAndView.addObject("accountUploadDate", DateUtils.addDays(session.getStartDate(), -12));
        modelAndView.addObject("reportUploadDate", DateUtils.addDays(session.getStartDate(), -2));
        
        // list session's all delegate
        List<Delegate> delegates = sessionService.listDelegate(session);
        modelAndView.addObject("delegates", delegates);
        
        // list session report
        Map<String, SessionReport> sessionReports = sessionReportService.list(session);
        modelAndView.addObject("sessionReports", sessionReports);
        
        // list evaluation task
        String[] names = new String[]{"Wave Evaluation", "Swift Evaluation"};
        Map<String, Map<String, SessionTask>> sessionTasks = sessionTaskService.listByName(session, names, Type.DELEGATE);
        modelAndView.addObject("sessionTasks", sessionTasks);
        
        return modelAndView;
    }
    
    /**
     * 
     * @param sessionId
     * @return
     */
    @RequestMapping(value = "/active-sessions/{sessionId}/account-template-export", method = RequestMethod.GET)
    public ModelAndView onExport(@PathVariable("sessionId") Long sessionId) {
        
        ModelAndView modelAndView = new ModelAndView(new ExcelTemplateView("account-template-export.xls", "account-template.xls"));
        
        Session session = sessionService.load(sessionId);
        
        // list session's all delegate
        List<Delegate> delegates = sessionService.listDelegate(session);
        modelAndView.addObject("delegates", delegates); 
        
        return modelAndView;
        
    }
    
    /**
     * 
     * @param sessionId
     * @return
     */
    @RequestMapping(value = "/active-sessions/{sessionId}/account-upload", method = RequestMethod.GET)
    public ModelAndView accountUpload(@PathVariable("sessionId") Long sessionId) {
        ModelAndView modelAndView = new ModelAndView("session/supervisor/online-account-upload");
        modelAndView.addObject("sessionId", sessionId);
        return modelAndView;
    }

    /**
     * 
     * @param sessionId
     * @param file
     * @return
     */
    @RequestMapping(value = "/active-sessions/{sessionId}/account-upload", method = RequestMethod.POST)
    public ModelAndView onAccountUpload(@PathVariable("sessionId") Long sessionId, @RequestParam("file") MultipartFile file) {
    
        ModelAndView modelAndView = new ModelAndView("redirect:/active-sessions/" + sessionId);
        
        try {
            
            List<OnlineAccount> onlineAccounts = onlineAccountUploadHandler.upload(file.getInputStream());
            delegateService.uploadOnlineAccount(onlineAccounts);
            
        } catch (Exception e) {
            modelAndView.addObject("errorMessage", e.getMessage());
        }
        
        return modelAndView;
        
    }
    
    /**
     * 
     * @param sessionId
     * @return
     */
    @RequestMapping(value = "/active-sessions/{sessionId}/report-upload", method = RequestMethod.GET)
    public ModelAndView reportUpload(@PathVariable("sessionId") Long sessionId) {
        ModelAndView modelAndView = new ModelAndView("session/supervisor/online-report-upload");
        
        Session session = sessionService.load(sessionId);
        modelAndView.addObject("session", session);
        
        // list session's all delegate
        List<Delegate> delegates = sessionService.listDelegate(session);
        modelAndView.addObject("delegates", delegates); 
        
        return modelAndView;
    }

    /**
     * 
     * @param operator
     * @param sessionId
     * @param onlineReport
     * @return
     */
    @RequestMapping(value = "/active-sessions/{sessionId}/report-upload", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    public ModelAndView onReportUpload(@Secure(property = "id") Long operator,
                                       @PathVariable("sessionId") Long sessionId,
                                       OnlineReportUpload onlineReport) {
        
        ModelAndView modelAndView = new ModelAndView("redirect:/active-sessions/" + sessionId);
        
        try {
            
            Session session = sessionService.load(sessionId);
            
            // upload ppt file
            String path = session.getName();
            List<OnlineReport> onlineReports = fileHandler.batchSave(path, onlineReport.getItems());
            
            sessionReportService.reportUpload(session, onlineReports, operator);
            
        } catch (Exception e) {
            logger.error("onReportUpload - create fail, exception [{}]", e);
        }
        
        return modelAndView;
        
    }
    
    /**
     * 
     * @param sessionId
     * @return
     */
    @RequestMapping(value = "/active-sessions/{sessionId}/data-upload", method = RequestMethod.GET)
    public ModelAndView dataUpload(@PathVariable("sessionId") Long sessionId) {
        ModelAndView modelAndView = new ModelAndView("session/supervisor/online-data-upload");
        
        modelAndView.addObject("sessionId", sessionId);
        
        return modelAndView;
    }

    /**
     * 
     * @param sessionId
     * @param waveData
     * @param swiftData
     * @return
     */
    @RequestMapping(value = "/active-sessions/{sessionId}/data-upload", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    public ModelAndView onDataUpload(@PathVariable("sessionId") Long sessionId,
                                     @RequestParam("waveData") MultipartFile waveData,
                                     @RequestParam("swiftData") MultipartFile swiftData) {
        
        ModelAndView modelAndView = new ModelAndView("redirect:/active-sessions/" + sessionId);
        
        try {
                Session session = sessionService.load(sessionId);
                
                // upload wave data file
                String path = session.getName() + "/data";
                FileStorage waveFileStorage = new FileStorage(path, "wave_data", FilenameUtils.getExtension(waveData.getOriginalFilename()));
                String waveDataUrl = fileHandler.save(waveFileStorage, waveData.getInputStream());
                
                // upload swift data file
                FileStorage swiftFileStorage = new FileStorage(path, "swift_data", FilenameUtils.getExtension(swiftData.getOriginalFilename()));
                String swiftDataUrl = fileHandler.save(swiftFileStorage, swiftData.getInputStream());
                
                sessionReportService.dataUpload(session, waveDataUrl, swiftDataUrl);
            
        } catch (Exception e) {
            
            logger.error("onDataUpload - create fail, exception [{}]", e);
            
        }
        
        return modelAndView;
        
    }
    
    /**
     * 
     * @param sessionId
     * @param delegateId
     * @param name
     * @return
     */
    @RequestMapping(value = "/active-sessions/{sessionId}/delegates/{delegateId}/upload", method = RequestMethod.GET)
    public ModelAndView delegateReportUpload(@PathVariable("sessionId") Long sessionId,
                                             @PathVariable("delegateId") Long delegateId,
                                             @RequestParam("name") String name) {
        ModelAndView modelAndView = new ModelAndView("session/supervisor/delegate-report-upload");
        
        modelAndView.addObject("sessionId", sessionId);
        modelAndView.addObject("delegateId", delegateId);
        modelAndView.addObject("name", name);
        
        return modelAndView;
    }

    /**
     * 
     * @param operator
     * @param sessionId
     * @param delegateId
     * @param name
     * @param report
     * @return
     */
    @RequestMapping(value = "/active-sessions/{sessionId}/delegates/{delegateId}/upload", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    public ModelAndView onDelegateReportUpload(@Secure(property = "id") Long operator,
                                               @PathVariable("sessionId") Long sessionId,
                                               @PathVariable("delegateId") Long delegateId,
                                               @RequestParam("name") String name,
                                               @RequestParam("report") MultipartFile report) {
        
        ModelAndView modelAndView = new ModelAndView("redirect:/active-sessions/" + sessionId);
        
        try {
                Session session = sessionService.load(sessionId);
                Delegate delegate = delegateService.load(Delegate.class, delegateId);
                
                // upload wave data file
                String path = session.getName() + "/" + delegate.getName() + "/report";
                FileStorage fileStorage = new FileStorage(path, ReportType.aliasOf(name).getDescription(), FilenameUtils.getExtension(report.getOriginalFilename()));
                String reportUrl = fileHandler.save(fileStorage, report.getInputStream());
                
                sessionReportService.reportUpload(session, delegate, reportUrl, name, operator);
            
        } catch (Exception e) {
            
            logger.error("onDelegateReportUpload - create fail, exception [{}]", e);
            
        }
        
        return modelAndView;
        
    }
    
    /**
     * 
     * @param sessionId
     * @param taskId
     * @return
     */
    @RequestMapping(value = "/active-sessions/{sessionId}/session-tasks/{taskId}/confirm-evaluation" , method = RequestMethod.GET)
    public ModelAndView confirmEvaluation(@PathVariable("sessionId") Long sessionId, @PathVariable("taskId") Long taskId) {
        
        ModelAndView modelAndView = new ModelAndView("session/supervisor/evaluation-confirm");
        
        modelAndView.addObject("sessionId", sessionId);
        modelAndView.addObject("taskId", taskId);
        
        return modelAndView;
        
    }
    
    /**
     * 
     * @param taskId
     * @return
     */
    @RequestMapping(value = "/active-sessions/{sessionId}/session-tasks/{taskId}/confirm-evaluation" , method = RequestMethod.PATCH, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    public @ResponseBody HttpResult onConfirmEvaluation(@PathVariable("taskId") Long taskId) {
        
        HttpResult httpResult = new HttpResult();
        
        try {
            
            SessionTask sessionTask = sessionTaskService.load(SessionTask.class, taskId);
            sessionTaskService.finishEvaluation(sessionTask);
            
            httpResult.success().message("successed");
            
        } catch (Exception e) {
            httpResult.fail("500").message("failed");
            logger.error("#onConfirmEvaluation() - ",e);
        }
        
        return httpResult;
        
    }

}
